<template>
  <div class="box" :style="{ zIndex: zIndex }">
    <Toolbar class="toolbarBox" :editor="editorRef" :default-config="toolbarConfig" />
    <Editor
      v-model="htmlValue"
      :default-config="editorConfig"
      :style="{ height: height + 'px' }"
      class="editorBox"
      @on-created="handleCreated"
      @on-change="handleEditorChange"
    />
    <textarea
      v-model="codeValue"
      :style="{ height: height + 'px' }"
      class="sourceBox"
      @change="handleSourceChange"
    ></textarea>
    <file-modal ref="fileModelRef" :multiple="true" @on-file-selected="handleSelectImageSubmit" />
  </div>
</template>

<script name="Editor" lang="ts" setup>
import "@wangeditor/editor/dist/css/style.css";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import type { IEditorConfig, IToolbarConfig } from "@wangeditor/editor";

const props = defineProps({
  value: {
    type: String,
    default: () => ""
  },
  height: {
    type: Number,
    default: 400
  },
  zIndex: {
    type: Number,
    default: 10000
  }
});

const emit = defineEmits(["update:value"]);

const editorRef = shallowRef();
const htmlValue = ref("");
const codeValue = ref("");
const fileModelRef = ref();

// 工具栏配置
const toolbarConfig: Partial<IToolbarConfig> = {
  excludeKeys: ["uploadVideo"],
  insertKeys: {
    index: 31,
    keys: ["showSource"]
  }
};

type InsertFnType = (url: string, alt: string, href: string) => void;
const editorConfig: Partial<IEditorConfig> = {
  autoFocus: false,
  placeholder: "请输入内容...",
  MENU_CONF: {
    uploadImage: {
      customBrowseAndUpload(insertFn: InsertFnType) {
        fileModelRef.value.show();
      }
    }
  }
};

watch(props, () => {
  htmlValue.value = props.value;
  codeValue.value = props.value;
});

onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) {
    return;
  }
  editor.destroy();
});

const handleCreated = editor => {
  editorRef.value = editor;
};

const handleEditorChange = editor => {
  emit("update:value", editor.getHtml());
};
const handleSourceChange = editor => {
  emit("update:value", codeValue.value);
};

const handleSelectImageSubmit = (result: any) => {
  const editor = editorRef.value;
  if (editor != null && result.length > 0) {
    result.forEach((item: any) => {
      editor.dangerouslyInsertHtml('<img alt="' + item.fileName + '" src="' + item.url + '" />');
    });
  }
};
</script>

<style lang="less" scoped>
.box {
  border: 1px solid #ccc;
  margin-top: 10px;

  .toolbarBox {
    border-bottom: 1px solid #ccc;
  }

  .editorBox {
    overflow-y: hidden;
  }

  .sourceBox {
    display: none;
    width: 100%;
    height: 200px;
    outline: none;
    border: none;
    overflow-y: hidden;
  }
}
</style>
